﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MathService.Values
{
    public class NumberedValues<TValue> : IEnumerable<KeyValuePair<double, TValue>>
    {
        private readonly double f_t0;
        private readonly double f_dt;
        private readonly TValue[] f_Values;
        public double t0 { get { return f_t0; } }
        public double dt { get { return f_dt; } }
        public int Count { get { return f_Values.Length; } }
        public double T { get { return Count * dt; } }

        public TValue this[int i] { get { return f_Values[i]; } set { f_Values[i] = value; } }

        public TValue this[double t] { get { return this[IndexOf(t)]; } set { this[IndexOf(t)] = value; } }

        public NumberedValues(double dt, int N, double t0 = 0) : this(dt, new TValue[N], t0) { }
        public NumberedValues(double dt, TValue[] Values, double t0 = 0)
        {
            f_t0 = t0;
            f_dt = dt;
            f_Values = Values;
        }

        public NumberedValues(double dt, IEnumerable<TValue> Values, double t0 = 0)
        {
            f_t0 = t0;
            f_dt = dt;
            f_Values = Values.ToArray();
        }

        public int IndexOf(double t)
        {
            var i = (int)Math.Round((t - f_t0) / dt);
            return i < 0 ? 0 : (i >= Count ? Count - 1 : i);
        }

        public IEnumerator<KeyValuePair<double, TValue>> GetEnumerator()
        {
            return f_Values.Cast<TValue>()
                        .Select((v, i) => new KeyValuePair<double, TValue>(i * f_dt + f_t0, v))
                        .GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

        public IEnumerable<TValue> GetValues() { return f_Values; }

        public IEnumerable<double> GetTimes()
        {
            return Enumerable.Range(0, Count)
                        .Select(i => i*f_dt + f_t0);
        } 
    }
}
